/**
 * Copyright (c) 2006-2015, JGraph Ltd
 * Copyright (c) 2006-2015, Gaudenz Alder
 */
var mxCodecRegistry =
    {
        /**
         * Class: mxCodecRegistry
         *
         * Singleton class that acts as a global registry for codecs.
         *
         * Adding an <mxCodec>:
         *
         * 1. Define a default codec with a new instance of the
         * object to be handled.
         *
         * (code)
         * var codec = new mxObjectCodec(new mxGraphModel());
         * (end)
         *
         * 2. Define the functions required for encoding and decoding
         * objects.
         *
         * (code)
         * codec.encode = function(enc, obj) { ... }
         * codec.decode = function(dec, node, into) { ... }
         * (end)
         *
         * 3. Register the codec in the <mxCodecRegistry>.
         *
         * (code)
         * mxCodecRegistry.register(codec);
         * (end)
         *
         * <mxObjectCodec.decode> may be used to either create a new
         * instance of an object or to configure an existing instance,
         * in which case the into argument points to the existing
         * object. In this case, we say the codec "configures" the
         * object.
         *
         * Variable: codecs
         *
         * Maps from constructor names to codecs.
         */
        codecs: [],

        /**
         * Variable: aliases
         *
         * Maps from classnames to codecnames.
         */
        aliases: [],

        /**
         * Function: register
         *
         * Registers a new codec and associates the name of the template
         * constructor in the codec with the codec object.
         *
         * Parameters:
         *
         * codec - <mxObjectCodec> to be registered.
         */
        register: function(codec)
        {
            if (codec != null)
            {
                var name = codec.getName();
                mxCodecRegistry.codecs[name] = codec;

                var classname = mxUtils.getFunctionName(codec.template.constructor);

                if (classname != name)
                {
                    mxCodecRegistry.addAlias(classname, name);
                }
            }

            return codec;
        },

        /**
         * Function: addAlias
         *
         * Adds an alias for mapping a classname to a codecname.
         */
        addAlias: function(classname, codecname)
        {
            mxCodecRegistry.aliases[classname] = codecname;
        },

        /**
         * Function: getCodec
         *
         * Returns a codec that handles objects that are constructed
         * using the given constructor.
         *
         * Parameters:
         *
         * ctor - JavaScript constructor function.
         */
        getCodec: function(ctor)
        {
            var codec = null;

            if (ctor != null)
            {
                var name = mxUtils.getFunctionName(ctor);
                var tmp = mxCodecRegistry.aliases[name];

                if (tmp != null)
                {
                    name = tmp;
                }

                codec = mxCodecRegistry.codecs[name];

                // Registers a new default codec for the given constructor
                // if no codec has been previously defined.
                if (codec == null)
                {
                    try
                    {
                        codec = new mxObjectCodec(new ctor());
                        mxCodecRegistry.register(codec);
                    }
                    catch (e)
                    {
                        // ignore
                    }
                }
            }

            return codec;
        }

    };
